package com.hsd.whb.controller;

import com.alibaba.fastjson.JSONObject;
import com.hsd.whb.converter.MeetingConverter;
import com.hsd.whb.entity.*;
import com.hsd.whb.enums.ResultEnum;
import com.hsd.whb.exception.HwbException;
import com.hsd.whb.pojo.input.ModifyPassword;
import com.hsd.whb.pojo.output.MeetingParticipateTextVO;
import com.hsd.whb.pojo.output.MeetingVO;
import com.hsd.whb.properties.PersonProperties;
import com.hsd.whb.repository.*;
import com.hsd.whb.security.recorder.RecorderAuthenticationToken;
import com.hsd.whb.service.*;
import com.hsd.whb.utils.*;
import com.hsd.whb.pojo.output.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.*;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/function")
public class FunctionController {

    @Autowired
    private ManagerRepository managerRepository;

    @Autowired
    private RecorderRepository recorderRepository;

    @Autowired
    private ParticipantsRepository participantsRepository;

    @Autowired
    private MeetingMateralsRepository meetingMateralsRepository;

    @Autowired
    private MeetingRepository meetingRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private MeetingMateralsService meetingMateralsService;

    @Autowired
    private MeetingService meetingService;

    @Autowired
    private MailSenderService mailSenderService;

    @Autowired
    private ParticipantsService participantsService;

    @Autowired
    private MeetingParticipateTextService meetingParticipateTextService;

    @Autowired
    private MeetingParticipantsService meetingParticipantsService;

    @Autowired
    private PersonProperties personProperties;


    /*
     *首面
     */
    @GetMapping("/showYe")
    public String toShouYe() {
        return "shouYe";
    }

    /*
     *主页面
     */
    @GetMapping("/main")
    public String toMain(HttpServletRequest request) {
        request.setAttribute("username", SecurityUtil.getUsername());
        if (SecurityUtil.hasRecorderRole()) {
            request.setAttribute("menusList", MenusUtil.generateRecorderMenus(request.getContextPath()));
            request.setAttribute("modifyInfoUrl", request.getContextPath() + "/recorder/modifyInfo");
            request.setAttribute("oneselfInfoUrl", request.getContextPath() + "/recorder/getOneselfInfo");
            return "main";
        } else if (SecurityUtil.hasRootRole()) {
            request.setAttribute("menusList", MenusUtil.generateRootMenus(request.getContextPath()));
            request.setAttribute("modifyInfoUrl", request.getContextPath() + "/manager/modifyInfo");
            request.setAttribute("oneselfInfoUrl", request.getContextPath() + "/manager/getOneselfInfo");
            return "main";
        } else {
            request.setAttribute("menusList", MenusUtil.generateManagerMenus(request.getContextPath()));
            request.setAttribute("modifyInfoUrl", request.getContextPath() + "/manager/modifyInfo");
            request.setAttribute("oneselfInfoUrl", request.getContextPath() + "/manager/getOneselfInfo");
            return "main";
        }
    }

    /*
     *获取头像
     */
    @GetMapping("/getImage")
    public ResponseEntity<byte[]> getImage() throws IOException {
        String avatar;
        String username = SecurityUtil.getUsername();
        if (SecurityUtil.hasRecorderRole()) {
            Recorder recorder = recorderRepository.findByUsername(username);
            avatar = recorder.getAvatar();
        } else {
            Manager manager = managerRepository.findByUsername(username);
            avatar = manager.getAvatar();
        }
        InputStream inputStream;
        if (StringUtils.isEmpty(avatar)) {
            inputStream = this.getClass().getResourceAsStream("/static/img/logo.jpg");
        } else {
            inputStream = new FileInputStream(avatar);
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(StreamUtils.copyToByteArray(inputStream), headers, HttpStatus.CREATED);
    }


    /*
     *修改密码页面
     */
    @GetMapping("/modifyPassword")
    public String toModifyPassword() {
        return "common/modifyPassword";
    }

    /*
     *修改密码
     */
    @PostMapping("/modifyPassword")
    @ResponseBody
    public ResultVO modifyPassword(@Valid ModifyPassword modifyPassword, BindingResult bindingResult, Authentication authentication, Principal principal) {
        ValidatorUtil.valid(bindingResult);
        if (authentication instanceof RecorderAuthenticationToken) {
            Recorder recorder = recorderRepository.findByUsername(principal.getName());
            modifyPassword.setPrePassword(recorder.getPassword());
            modifyPassword.valid(passwordEncoder);
            recorder.setPassword(passwordEncoder.encode(modifyPassword.getNewPassword()));
            recorderRepository.save(recorder);
        } else {
            Manager manager = managerRepository.findByUsername(principal.getName());
            modifyPassword.setPrePassword(manager.getPassword());
            modifyPassword.valid(passwordEncoder);
            manager.setPassword(passwordEncoder.encode(modifyPassword.getNewPassword()));
            managerRepository.save(manager);
        }
        return ResultVOUtil.success("修改成功，请重新登录");
    }

    @GetMapping("/getPersonListByName")
    @ResponseBody
    public List getPersonListByName(String username) {
        List managerList = managerRepository.findByUsernameLikeAndDeleted("%" + username + "%", 0);
        List recorderList = recorderRepository.findByUsernameLikeAndDeleted("%" + username + "%", 0);
        List participantsList = participantsRepository.findByUsernameLikeAndDeleted("%" + username + "%", 0);
        List list = new ArrayList();
        list.addAll(managerList);
        list.addAll(recorderList);
        list.addAll(participantsList);
        return list;
    }

    /*
     *上传头像
     */
    @PostMapping("/uploadImage")
    @ResponseBody
    public ResultVO uploadImage(@RequestParam("file") MultipartFile multipartFile) {
        String username = SecurityUtil.getUsername();
        if (SecurityUtil.hasRecorderRole()) {
            String parentUrl = personProperties.getImage() + "/recorder/" + username;
            FileUtil.delAllFile(parentUrl);
            String filename = FileUtil.copyToFile(multipartFile, parentUrl);
            Recorder recorder = recorderRepository.findByUsername(username);
            recorder.setAvatar(parentUrl + "/" + filename);
            recorderRepository.save(recorder);
        } else {
            String parentUrl = personProperties.getImage() + "/manager/" + username;
            FileUtil.delAllFile(parentUrl);
            String filename = FileUtil.copyToFile(multipartFile, parentUrl);
            Manager manager = managerRepository.findByUsername(username);
            manager.setAvatar(parentUrl + "/" + filename);
            managerRepository.save(manager);
        }
        return ResultVOUtil.success("上传成功");
    }


    /*
     *获取头像
     */
    @GetMapping("/getAvatar")
    public ResponseEntity<byte[]> getImage(String avatar) throws IOException {
        if (!avatar.startsWith(personProperties.getImage())) throw new HwbException(500, "文件路径不正确");
        InputStream inputStream = new FileInputStream(avatar);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(StreamUtils.copyToByteArray(inputStream), headers, HttpStatus.CREATED);
    }

    @GetMapping("/downloadFile")
    public ResponseEntity<byte[]> downloadFile(String filePath) throws IOException {
        if (!filePath.startsWith(personProperties.getImage() + "/meetingMaterals"))
            throw new HwbException(500, "文件路径不正确");
        InputStream inputStream = new FileInputStream(filePath);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", new String(FileUtil.getFileName(filePath).getBytes("utf-8"), "iso8859-1"));
        return new ResponseEntity<byte[]>(StreamUtils.copyToByteArray(inputStream), headers, HttpStatus.CREATED);
    }

    @GetMapping("/downloadZipFile")
    public ResponseEntity<byte[]> downloadZipFile(Integer meetingId) throws IOException {
        Meeting meeting = meetingRepository.getOne(meetingId);
        String filePath = personProperties.getImage() + "/meetingMaterals/" + meetingId;
        File parentFile = new File(filePath);
        if (!parentFile.exists()) parentFile.mkdirs();
        File[] fileList = parentFile.listFiles();
        File zipFile = new File(parentFile, meeting.getTitle() + ".zip");
        FileUtil.zipFile(fileList, zipFile);
        InputStream inputStream = new FileInputStream(zipFile);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", new String(zipFile.getName().getBytes("utf-8"), "iso8859-1"));
        return new ResponseEntity<byte[]>(StreamUtils.copyToByteArray(inputStream), headers, HttpStatus.CREATED);
    }

    @GetMapping("/downloadMeetingFile")
    public ResponseEntity<byte[]> downloadMeetingFile(Integer meetingId, Integer intervalSeconds) throws Exception {
        if (intervalSeconds == null) intervalSeconds = 3;
        Meeting meeting = meetingRepository.getOne(meetingId);
        File file = new File(personProperties.getImage() + "/meetingMaterals/" + meetingId + "/" + meeting.getTitle() + ".doc");
        JSONObject jsonObject = meetingParticipateTextService.getMeetingFileDataByMeetingId(meetingId, intervalSeconds);
        System.out.println(jsonObject);
        FreemarkerUtil.generateFile("meeting.xml", file.getAbsolutePath(), jsonObject);
        InputStream inputStream = new FileInputStream(file);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", new String(file.getName().getBytes("utf-8"), "iso8859-1"));
        return new ResponseEntity<byte[]>(StreamUtils.copyToByteArray(inputStream), headers, HttpStatus.CREATED);
    }


    @GetMapping("/getAllFileByMeetingId")
    @ResponseBody
    public List<Map> getAllFileByMeetingId(Integer meetingId) {
        MeetingMaterals meetingMaterals = meetingMateralsService.findByMeetingId(meetingId);
        return meetingMateralsService.getMapByMeetingMaterals(meetingMaterals);
    }

    @PostMapping("/uploadMeetingMaterals")
    @ResponseBody
    public ResultVO uploadMeetingMaterals(@RequestParam("file") MultipartFile multipartFile,
                                          Integer meetingId, String location) {
        MeetingMaterals meetingMaterals = meetingMateralsService.findByMeetingId(meetingId);
        if (meetingMaterals == null) {
            meetingMaterals = new MeetingMaterals();
            meetingMaterals.setMeetingId(meetingId);
            meetingMaterals.setDeleted(0);
        } else {
            String path = (String) BeanUtil.getValueByPropertyNames(meetingMaterals, location);
            System.out.println(path);
            if (path != null) {
                new File(path).delete();
            }
        }
        String parentUrl = personProperties.getImage() + "/meetingMaterals/" + meetingId;
        File parentFile = new File(parentUrl);
        if (!parentFile.exists()) parentFile.mkdirs();
        try {
            multipartFile.transferTo(new File(parentFile, multipartFile.getOriginalFilename()));
        } catch (IOException e) {
            e.printStackTrace();
            throw new HwbException(ResultEnum.UPLOAD_FILE_ERROR);
        }
        BeanUtil.setValueByPropertyNames(meetingMaterals, location, parentUrl + "/" + multipartFile.getOriginalFilename());
        meetingMateralsService.save(meetingMaterals);
        return ResultVOUtil.success();
    }

    @GetMapping("/getMeetingById")
    @ResponseBody
    public MeetingVO getMeetingById(Integer id) {
        Meeting meeting = meetingService.findMeetingById(id);
        return MeetingConverter.convertToMeetingVO(meeting);
    }

    @GetMapping("/getParticipateByMeetingId")
    @ResponseBody
    public List<Participants> getParticipateByMeetingId(Integer meetingId) {
        List<Integer> list = meetingParticipantsService.getParticipantsIdByMeetingId(meetingId);
        return participantsService.findParticipantsByIdInList(list);
    }


    @GetMapping("/getMeetingTextByMeetingId")
    @ResponseBody
    public List<MeetingParticipateTextVO> getMeetingTextByMeetingId(Integer meetingId) {
        return meetingParticipateTextService.getMeetingTextByMeetingId(meetingId);
    }

    @PostMapping("/updateMeetingAbstractById")
    @ResponseBody
    public ResultVO updateMeetingAbstractById(Integer id, String meetingAbstract) {
        Meeting meeting = meetingService.findMeetingById(id);
        meeting.setMeetingAbstract(meetingAbstract);
        meetingService.save(meeting);
        return ResultVOUtil.success("修改成功");
    }

    @PostMapping("/sendEmail")
    @ResponseBody
    public ResultVO sendEmail(String email, Integer meetingId) throws Exception {
        Meeting meeting = meetingService.findMeetingById(meetingId);
        String parentUrl = personProperties.getImage() + "/meetingMaterals/" + meetingId;
        File parentFile = new File(parentUrl);
        mailSenderService.sendMail(email, meeting.getTitle(), meeting.getTitle() + "会议材料下载", parentFile.listFiles());
        return ResultVOUtil.success("发送成功");
    }

    @GetMapping("/fileRecordForm/{meetingId}")
    public String toFileRecordForm(@PathVariable("meetingId") Integer meetingId, HttpServletRequest request) {
        request.setAttribute("meetingId", meetingId);
        return "common/fileRecordForm";
    }

    @PostMapping("/deleteFileRecordById")
    @ResponseBody
    public ResultVO deleteFileRecordById(Integer id) {
        Meeting meeting = meetingService.findMeetingById(id);
        meeting.setDeleted(1);
        meetingService.save(meeting);
        return ResultVOUtil.success("删除成功");
    }

    @GetMapping("/searchPersonByName")
    public String toSearchPersonByName() {
        return "common/searchPersonByName";
    }


    @GetMapping("/participateList")
    public String toParticipateList() {
        return "common/participateList";
    }

    @GetMapping("/participateForm")
    public String toParticipateForm() {
        return "common/participateForm";
    }


    @PostMapping("/findParticipateList")
    @ResponseBody
    public List<Participants> findParticipateList(@PageableDefault(sort = "workNumber", direction = Sort.Direction.DESC) Pageable pageable,
                                                  Participants participants) {
        Integer managerId;
        if (SecurityUtil.hasRecorderRole()) {
            Recorder recorder = recorderRepository.findByUsername(SecurityUtil.getUsername());
            managerId = recorder.getManagerId();
        } else {
            Manager manager = managerRepository.findByUsername(SecurityUtil.getUsername());
            managerId = manager.getId();
        }
        return participantsService.findParticipateList(pageable, managerId, participants);
    }

    @GetMapping("/findParticipateList")
    @ResponseBody
    public long findParticipateListTotalPages(Integer size, Participants participants) {
        Integer managerId;
        if (SecurityUtil.hasRecorderRole()) {
            Recorder recorder = recorderRepository.findByUsername(SecurityUtil.getUsername());
            managerId = recorder.getManagerId();
        } else {
            Manager manager = managerRepository.findByUsername(SecurityUtil.getUsername());
            managerId = manager.getId();
        }
        long totalNum = participantsService.findParticipateListTotalPages(managerId, participants);
        ;
        return (long) Math.ceil(totalNum / (double) size);
    }

    @PostMapping("/deleteParticipateById")
    @ResponseBody
    public ResultVO deleteParticipateById(Integer id) {
        Participants participants = participantsService.findParticipantsById(id);
        participants.setDeleted(1);
        participantsService.update(participants);
        return ResultVOUtil.success("删除成功");
    }

    @GetMapping("/findParticipateById")
    @ResponseBody
    public Participants findParticipateById(Integer id) {
        Participants participants = participantsService.findParticipantsById(id);
        return participants;
    }

    @PostMapping("/updateParticipate")
    @ResponseBody
    public ResultVO updateParticipate(@RequestParam(name = "file", required = false) MultipartFile multipartFile, @Valid Participants participants, BindingResult bindingResult) {
        ValidatorUtil.valid(bindingResult);
        String msg;
        if (multipartFile != null) {
            String parentUrl = personProperties.getImage() + "/participants/" + participants.getUsername();
            String filename = FileUtil.copyToFile(multipartFile, parentUrl);
            if (participants.getId() == null) {
                participants.setDeleted(0);
                participants.setAvatar(parentUrl + "/" + filename);
                if (SecurityUtil.hasRecorderRole()) {
                    Recorder recorder = recorderRepository.findByUsername(SecurityUtil.getUsername());
                    participants.setManagerId(recorder.getManagerId());
                } else {
                    Manager manager = managerRepository.findByUsername(SecurityUtil.getUsername());
                    participants.setManagerId(manager.getId());
                }
                participantsService.save(participants);
                msg = "添加成功";
            } else {
                Participants target = participantsService.findParticipantsById(participants.getId());
                BeanUtil.copyPropertiesIgnoreNull(participants, target);
                target.setAvatar(parentUrl + "/" + filename);
                participantsService.update(target);
                msg = "修改成功";
            }
        } else {
            Participants target = participantsService.findParticipantsById(participants.getId());
            BeanUtil.copyPropertiesIgnoreNull(participants, target);
            participantsService.update(target);
            msg = "修改成功";
        }
        return ResultVOUtil.success(msg);
    }

    @GetMapping("/getParticipateListByName")
    @ResponseBody
    public List<Participants> getParticipateListByName(String username, String existName) {
        return participantsService.getParticipateListByName("%" + username + "%", existName);
    }


}
